<template>
  <div class="edit">
    <!-- 导航部分 -->
    <van-nav-bar title="编辑资料" left-arrow @click-left="$router.back()" />
    <!-- 头像盒子 -->
    <div class="Head-box">
      <!-- 放文件上传 after-read是个钩子函数，当我选择确定文件时会调用-->
      <van-uploader :after-read="afterRead" />
      <van-image fit="cover" round :src="userInfo.photo" />
    </div>
    <!-- 底部的三个cell显示：姓名、性别、年龄 -->
    <van-cell-group>
      <van-cell
        @click="doEditName"
        title="名称"
        :value="userInfo.name"
        is-link
      />
      <van-cell
        @click="sexShow = true"
        title="性别"
        :value="userInfo.gender ? '男' : '女'"
        is-link
      />
      <van-cell
        @click="doeEitBitehday"
        title="生日"
        :value="userInfo.birthday"
        is-link
      />
    </van-cell-group>
    <!-- 添加弹框框 用来修改姓名 -->
    <van-dialog
      @confirm="updateName"
      v-model="nameShow"
      title="修改名字"
      show-cancel-button
    >
      <van-field ref="nameInp" v-model="editName" />
    </van-dialog>
    <!-- 添加从下出现的弹出框用来修改性别 -->
    <van-popup class="sex" v-model="sexShow" position="bottom">
      <van-nav-bar
        @click-left="sexShow = false"
        title="修改性别"
        left-text="取消"
      />
      <van-cell @click="editGender(1)" title="男" is-link />
      <van-cell @click="editGender(0)" title="女" is-link />
    </van-popup>
    <!-- 修改生日 -->
    <!-- 准备一个弹出层 -->
    <van-popup class="birthday" v-model="birthdayShow" position="bottom">
      <!-- 准备一个日期插件 -->
      <van-datetime-picker
        @cancel="birthdayShow = false"
        @confirm="editBirthday"
        v-model="currentDate"
        type="date"
        title="选择年月日"
        :min-date="minDate"
        :max-date="maxDate"
      />
    </van-popup>
    <!-- 图片裁剪容器 -->
    <div class="crop-box" v-if="cropShow">
      <!-- ref:方便后面通过$refs找到它 
      img：设置要剪裁的图片
      autocrop：代表产生一个剪裁框
      设置剪裁框的宽高-->
      <vueCropper
        ref="cropper"
        :img="cropImg"
        autoCrop
        autoCropWidth="180"
        autoCropHeight="180"
      ></vueCropper>
      <van-button @click="doCrop" type="primary">裁剪</van-button>
      <van-button @click="cropShow = false" type="primary">取消</van-button>
    </div>
  </div>
</template>

<script>
// 导入事件插件
import moment from "moment";
// 导入裁剪器
import { VueCropper } from "vue-cropper";
import { editUserInfoAPI, changeUserPhotoAPI } from "@/api";
export default {
  // 注册裁剪器
  components: {
    VueCropper,
  },
  data() {
    return {
      nameShow: false,
      editName: "",
      sexShow: false,
      birthdayShow: false,
      // 最小选择日期
      minDate: new Date(1949, 0, 1),
      // 最大选择日期
      maxDate: new Date(),
      // 当前选择日期
      currentDate: new Date(2021, 0, 17),
      cropShow: false,
      cropImg: "",
    };
  },
  methods: {
    doEditName() {
      // 让弹框显示
      this.nameShow = true;
      // 把名字渲染到弹框上
      this.editName = this.userInfo.name;
      // 再下一次dom更新时让输入阔获得焦点
      // 提示：$nextTick也可以用await，彻底杜绝回调函数，大家自己可以试
      this.$nextTick(() => {
        this.$refs.nameInp.focus();
      });
    },
    async updateName() {
      // 非空判断
      if (this.editName == "") return this.$total("请输入名字");
      await editUserInfoAPI({
        name: this.editName,
      });
      this.$store.commit("saveUserInfo", {
        ...this.userInfo,
        name: this.editName,
      });
    },
    // 修改性别
    async editGender(gender) {
      // 发起数据请求
      await editUserInfoAPI({
        gender,
      });
      // 修改vuex中的数据
      this.$store.commit("saveUserInfo", {
        ...this.userInfo,
        gender,
      });
      // 隐藏pop弹出
      this.sexShow = false;
    },
    doeEitBitehday() {
      // 把当前的生日赋给currentDate
      this.currentDate = new Date(this.userInfo.birthday);
      // 让弹框显示
      this.birthdayShow = true;
    },
    // 修改生日
    async editBirthday() {
      // 发起数据请求
      // 因为我们在日期组件里获取到的是日期对象，接口要求传的是字符串
      // 所以我们需要对日期对象进行处理，改成字符串形式：“YYYY-MM-DD”
      const birthday = moment(this.currentDate).format("YYYY-MM-DD");
      await editUserInfoAPI({
        birthday,
      });
      // 修改vuex里的数据
      this.$store.commit("saveUserInfo", {
        ...this.userInfo,
        birthday,
      });
      // 让pop框隐藏
      this.birthdayShow = false;
    },
    afterRead(data) {
      //  当我选择好图片后会有一个图片的对象还有base64
      // 把选择图片的base64给裁剪绑定的img
      this.cropImg = data.content;
      // 把裁剪容器显示出来
      this.cropShow = true;
    },
    // 剪裁
    doCrop() {
      // 发起请求获取新的头像路径
      // 找到名为cropper的盒子/容器，然后调用getCropBolob这个方法
      // 此方法获取到剪裁后（图片）的文件对象
      // 参数data：是裁剪后的对象文件
      this.$refs.cropper.getCropBlob(async (data) => {
        // ajax不能直接上传文件，要上传文件必须要用到FormData这个对象（即ajax2.0，因为ajax2.0之前是没有办法上传文件的）
        // 如果jquery要用FormData上传文件，在发送请求时要设置contentType和processData都为false，因为pot方法有自己的加密方式而formData也有自己的加密方式
        let fm = new FormData();
        fm.append("photo", data);
        // 直接把FormData作为对象参数传递进去
        let res = await changeUserPhotoAPI(fm);
        // 保存到vuex里
        this.$store.commit("saveUserInfo", {
          ...this.userInfo,
          photo: res.data.data.photo, //是服务器返回图片上传后的地址
        });
        // 隐藏剪裁区
        this.cropShow = false;
      });
    },
  },
  created() {
    //    调用vuex对象中获取数据的函数获取用户信息
    this.$store.dispatch("getUserInfo");
  },
  computed: {
    //   计算属性只要依赖项有改变，结果也会跟着变
    userInfo() {
      return this.$store.state.userInfo;
    },
  },
};
</script>

<style lang='less' scoped>
.edit {
  .Head-box {
    @h: 120px;
    height: @h;
    display: flex;
    justify-content: center;
    align-items: center;
    .van-image {
      width: 100px;
      height: 100px;
    }
    .van-uploader {
      position: absolute;
      z-index: 999;
      ::v-deep .van-uploader__upload {
        width: 100vw;
        height: @h;
        opacity: 0;
      }
    }
  }
  .van-field {
    border: 1px solid #ddd;
  }
  .sex {
    height: 140px;
  }
  .birthday {
    height: 220px;
  }
  .crop-box {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    .van-button {
      position: absolute;
      bottom: 0;
      // 找到最后一个button
      &:last-of-type {
        right: 0;
      }
    }
  }
}
</style>